package com.yjymm.commonsdk.common.aop;

import com.yjymm.commonsdk.common.annotation.Permission;
import com.yjymm.commonsdk.common.annotation.Permissions;
import com.yjymm.commonsdk.common.exception.PermissionBusinessException;
import com.yjymm.commonsdk.common.exception.en.PermissionResultEnum;
import com.yjymm.commonsdk.config.PermissionConfig;
import com.yjymm.commonsdk.config.TestConfig;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;

import javax.swing.*;
import java.lang.reflect.Method;

/**
 * @author panhaoxiong
 * @date 2021-02-08 13:43
 */

@Aspect
@Component
@AutoConfigureAfter({PermissionConfig.class})
public class PermissionAop {

    /**
     * 单个permission注解的切入点
     */
    @Pointcut("@annotation(com.yjymm.commonsdk.common.annotation.Permission)")
    public void permissionCut(){}


    /**
     * 多个permission注解的切入点
     */
    @Pointcut("@annotation(com.yjymm.commonsdk.common.annotation.Permissions)")
    public void multPermissionCut(){}


    @Before("permissionCut()")
    public void permissionBefore(JoinPoint joinPoint) throws Exception {
        Method method = getMethod(joinPoint);
        Permission annotation = method.getAnnotation(Permission.class);
        if (!verify(annotation)) {
            throw new PermissionBusinessException(PermissionResultEnum.VARIFY_ERROR.getCode(), PermissionResultEnum.VARIFY_ERROR.getMessage());
        }
    }

    @Before("multPermissionCut()")
    public void multPermissionBefore(JoinPoint joinPoint) throws Exception {
        Method method = getMethod(joinPoint);
        Permissions annotation = method.getAnnotation(Permissions.class);
        if (annotation != null) {
            Permission[] value = annotation.value();
            for (Permission permission : value) {
                if (!verify(permission)) {
                    throw new PermissionBusinessException(PermissionResultEnum.VARIFY_ERROR.getCode(), PermissionResultEnum.VARIFY_ERROR.getMessage());
                }
            }
        }
    }

    private Boolean verify(Permission permission) throws Exception {
        if (permission.propertyName() != null && permission.propertyValue() != null) {
            RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes();
            String value = (String) requestAttributes.getAttribute(permission.propertyName(), RequestAttributes.SCOPE_REQUEST);
            return permission.propertyValue().equals(value);
        } else {
            return permission.verifier().newInstance().doVerify();
        }
    }

    private Method getMethod(JoinPoint joinPoint) {
        Signature signature = joinPoint.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        return methodSignature.getMethod();
    }
}
